﻿using System;
using System.Threading.Tasks;
using System.Threading;

namespace DotnetUtil.Threading
{
    public sealed class AsyncWorkHelper
    {
        public bool Pause { get; set; }

        private Task _task;
        private CancellationTokenSource _tokenSource;

        private readonly Func<Task> _function;
        private readonly int _actionInterval;

        public AsyncWorkHelper(Func<Task> function, int actionInterval)
        {
            _function = function;
            _actionInterval = actionInterval;
        }

        public void Start(bool pause = false)
        {
            Pause = pause;
            _tokenSource = new CancellationTokenSource();
            _task = Task.Factory.StartNew(
                async () => { await DoWorkAsync(_tokenSource.Token); },
                TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach
            );
        }

        public void Stop()
        {
            _tokenSource?.Cancel();
            _task?.Wait();
            _task?.Dispose();
            _task = null;
            _tokenSource?.Dispose();
            _tokenSource = null;
        }

        private async Task DoWorkAsync(CancellationToken token)
        {
            while (true)
            {
                try
                {
                    await Task.Delay(_actionInterval, token);
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    if (!Pause)
                    {
                        await _function.Invoke();
                    }
                }
                catch (TaskCanceledException)
                {
                    break;
                }
            }
        }
    }
}
